#include "securetokenmanager.h"
#include "configmanager.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkInterface>
#include <QHostAddress>
#include <QRegularExpression>
#include <QCoreApplication>
#include <QDir>
#include <QFile>
#ifdef __linux__
#include <sys/mount.h>
#include <sys/param.h>
#endif
#include <sys/stat.h>

// 静态成员初始化
SecureTokenManager* SecureTokenManager::s_instance = nullptr;
const QString SecureTokenManager::TOKEN_VERSION = "1.0";
const QString SecureTokenManager::FAILED_ATTEMPT_KEY_PREFIX = "failed_attempts_";

SecureTokenManager::SecureTokenManager()
    : m_tokenExpirationHours(24 * 7)  // 默认7天过期
    , m_maxFailedAttempts(5)          // 默认最多5次失败尝试
{

    // 生成初始加密密钥
    m_currentEncryptionKey = deriveKeyFromHardware();
    m_keyGenerationTime = QDateTime::currentDateTime();

    // 缓存硬件ID
    m_cachedHardwareId = collectHardwareFingerprint();

}

SecureTokenManager::~SecureTokenManager()
{
}

SecureTokenManager& SecureTokenManager::instance()
{
    if (!s_instance) {
        s_instance = new SecureTokenManager();
    }
    return *s_instance;
}

QString SecureTokenManager::encryptAndStoreToken(const QString& token, const QString& email)
{

    // 检查Token是否被锁定
    if (!email.isEmpty() && isTokenLocked(email)) {
        return QString();
    }

    try {
        // 生成安全的nonce
        QByteArray nonce = generateIV();
        QString salt = generateSalt();

        // 生成加密密钥
        QByteArray encryptionKey = deriveKeyFromHardware(salt);

        // 加密Token
        QByteArray encryptedData = encryptAES256GCM(token.toUtf8(), encryptionKey, nonce);

        // 创建Token数据结构
        SecureTokenData tokenData;
        tokenData.version = TOKEN_VERSION;
        tokenData.encryptedData = encodeBase64Safe(encryptedData);
        tokenData.nonce = encodeBase64Safe(nonce);
        tokenData.salt = salt;
        tokenData.hash = calculateTokenHash(token, salt);
        tokenData.timestamp = QDateTime::currentSecsSinceEpoch();
        tokenData.expiresAt = tokenData.timestamp + (m_tokenExpirationHours * 3600);
        tokenData.failedAttempts = 0;

        // 序列化并存储
        QJsonObject tokenJson = tokenData.toJson();
        QString storageKey = email.isEmpty() ? "secureToken" : QString("secureToken_%1").arg(email);
        ConfigManager::setNestedValue("security", storageKey, QJsonDocument(tokenJson).toJson(QJsonDocument::Compact));
        ConfigManager::sync();

        // 清除失败尝试记录
        clearFailedAttempts(email);


        return tokenData.hash;

    } catch (const std::exception& e) {
        recordFailedAttempt(email);
        return QString();
    }
}

QString SecureTokenManager::loadAndDecryptToken(const QString& email)
{

    // 检查Token是否被锁定
    if (!email.isEmpty() && isTokenLocked(email)) {
        return QString();
    }

    try {
        // 从配置中读取加密Token
        QString storageKey = email.isEmpty() ? "secureToken" : QString("secureToken_%1").arg(email);
        QString tokenDataStr = ConfigManager::getNestedValue("security", storageKey, "").toString();

        if (tokenDataStr.isEmpty()) {
            return QString();
        }

        // 解析Token数据
        QJsonDocument doc = QJsonDocument::fromJson(tokenDataStr.toUtf8());
        if (!doc.isObject()) {
            recordFailedAttempt(email);
            return QString();
        }

        SecureTokenData tokenData = SecureTokenData::fromJson(doc.object());

        // 验证Token数据完整性
        if (!tokenData.isValid()) {
            recordFailedAttempt(email);
            return QString();
        }

        // 检查Token是否过期
        if (isTokenExpired(tokenData)) {
            clearStoredToken(email);
            return QString();
        }

        // 解密Token
        QByteArray nonce = decodeBase64Safe(tokenData.nonce);
        QByteArray encryptionKey = deriveKeyFromHardware(tokenData.salt);
        QByteArray decryptedData = decryptAES256GCM(decodeBase64Safe(tokenData.encryptedData), encryptionKey, nonce);

        QString token = QString::fromUtf8(decryptedData);

        // 验证解密结果的完整性
        QString expectedHash = calculateTokenHash(token, tokenData.salt);
        if (expectedHash != tokenData.hash) {
            recordFailedAttempt(email);
            return QString();
        }

        // 清除失败尝试记录
        clearFailedAttempts(email);


        return token;

    } catch (const std::exception& e) {
        recordFailedAttempt(email);
        return QString();
    }
}

void SecureTokenManager::clearStoredToken(const QString& email)
{
    QString storageKey = email.isEmpty() ? "secureToken" : QString("secureToken_%1").arg(email);
    ConfigManager::setNestedValue("security", storageKey, QString());
    ConfigManager::sync();

    // 清除失败尝试记录
    clearFailedAttempts(email);

}

bool SecureTokenManager::isTokenValid(const QString& encryptedToken)
{
    if (encryptedToken.isEmpty()) {
        return false;
    }

    // 这里可以添加额外的验证逻辑
    // 目前主要检查格式和完整性
    return encryptedToken.length() > 20;  // 基本长度检查
}

bool SecureTokenManager::isTokenExpired(const QString& encryptedToken)
{
    // 如果提供了加密Token字符串，先解析
    if (!encryptedToken.isEmpty()) {
        try {
            QJsonDocument doc = QJsonDocument::fromJson(encryptedToken.toUtf8());
            if (doc.isObject()) {
                SecureTokenData tokenData = SecureTokenData::fromJson(doc.object());
                return QDateTime::currentSecsSinceEpoch() > tokenData.expiresAt;
            }
        } catch (...) {
            // 解析失败，认为过期
            return true;
        }
    }

    // 否则检查当前用户的Token
    QString token = loadAndDecryptToken();
    return token.isEmpty();
}

bool SecureTokenManager::isTokenExpired(const SecureTokenData& tokenData)
{
    return QDateTime::currentSecsSinceEpoch() > tokenData.expiresAt;
}

qint64 SecureTokenManager::getTokenRemainingTime(const QString& encryptedToken)
{
    if (encryptedToken.isEmpty()) {
        return 0;
    }

    try {
        QJsonDocument doc = QJsonDocument::fromJson(encryptedToken.toUtf8());
        if (doc.isObject()) {
            SecureTokenData tokenData = SecureTokenData::fromJson(doc.object());
            qint64 remaining = tokenData.expiresAt - QDateTime::currentSecsSinceEpoch();
            return qMax(0LL, remaining);
        }
    } catch (...) {
        // 解析失败
        return 0;
    }

    return 0;
}

void SecureTokenManager::rotateEncryptionKey()
{

    // 生成新的加密密钥
    m_currentEncryptionKey = deriveKeyFromHardware(generateSalt());
    m_keyGenerationTime = QDateTime::currentDateTime();

}

bool SecureTokenManager::needsKeyRotation()
{
    return m_keyGenerationTime.daysTo(QDateTime::currentDateTime()) >= KEY_ROTATION_DAYS;
}

QString SecureTokenManager::generateSecureNonce()
{
    QByteArray nonce = generateIV();
    return encodeBase64Safe(nonce);
}

bool SecureTokenManager::verifyTokenIntegrity(const QString& encryptedToken, const QString& expectedHash)
{
    if (encryptedToken.isEmpty() || expectedHash.isEmpty()) {
        return false;
    }

    try {
        QJsonDocument doc = QJsonDocument::fromJson(encryptedToken.toUtf8());
        if (doc.isObject()) {
            SecureTokenData tokenData = SecureTokenData::fromJson(doc.object());
            return tokenData.hash == expectedHash;
        }
    } catch (...) {
        return false;
    }

    return false;
}

void SecureTokenManager::setTokenExpirationHours(int hours)
{
    m_tokenExpirationHours = qMax(1, hours);
}

void SecureTokenManager::setMaxFailedAttempts(int attempts)
{
    m_maxFailedAttempts = qMax(1, attempts);
}

bool SecureTokenManager::isTokenLocked(const QString& email)
{
    if (email.isEmpty()) {
        return false;
    }

    int failedAttempts = getFailedAttempts(email);
    bool isLocked = failedAttempts >= m_maxFailedAttempts;

    if (isLocked) {
    }

    return isLocked;
}

QString SecureTokenManager::collectHardwareFingerprint()
{
    QStringList hardwareComponents;

    // 收集CPU信息
    QString cpuId = getCpuId();
    if (!cpuId.isEmpty()) {
        hardwareComponents << "CPU:" + cpuId;
    }

    // 收集MAC地址
    QString macAddress = getMacAddress();
    if (!macAddress.isEmpty()) {
        hardwareComponents << "MAC:" + macAddress;
    }

    // 收集主板序列号
    QString mbSerial = getMotherboardSerial();
    if (!mbSerial.isEmpty()) {
        hardwareComponents << "MB:" + mbSerial;
    }

    // 收集磁盘序列号
    QString volumeSerial = getVolumeSerial();
    if (!volumeSerial.isEmpty()) {
        hardwareComponents << "VOL:" + volumeSerial;
    }

    // 生成硬件指纹
    QString fingerprint = hardwareComponents.join("|");
    QString hash = QCryptographicHash::hash(fingerprint.toUtf8(), QCryptographicHash::Sha256).toHex();


    return hash;
}

QString SecureTokenManager::getMotherboardSerial()
{
#ifdef _WIN32
    // Windows主板序列号获取
    DWORD bufferSize = 0;

    // 获取系统嵌入产品信息
    GetSystemFirmwareTable('RSMB', 0, nullptr, 0);
    bufferSize = GetLastError();

    if (bufferSize > 0) {
        QByteArray buffer(bufferSize, 0);
        if (GetSystemFirmwareTable('RSMB', 0, buffer.data(), bufferSize)) {
            // 简化版本：从SMBIOS中提取主板信息
            // 这里返回一个基于系统信息的哈希
            QString systemInfo = QString::number(GetSystemMetrics(SM_CXSCREEN)) +
                              QString::number(GetSystemMetrics(SM_CYSCREEN));
            return QCryptographicHash::hash(systemInfo.toUtf8(), QCryptographicHash::Md5).toHex().left(16);
        }
    }

    // 备用方案：使用系统信息
    QString computerName = qEnvironmentVariable("COMPUTERNAME");
    return QCryptographicHash::hash(computerName.toUtf8(), QCryptographicHash::Md5).toHex().left(16);

#elif __APPLE__
    // macOS主板序列号
    io_service_t platformExpert = IOServiceGetMatchingService(kIOMainPortDefault,
                                                            IOServiceMatching("IOPlatformExpertDevice"));
    if (platformExpert) {
        CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,
                                                                          CFSTR(kIOPlatformSerialNumberKey),
                                                                          kCFAllocatorDefault, 0);
        if (serialNumberAsCFString) {
            char buffer[256];
            if (CFStringGetCString((CFStringRef)serialNumberAsCFString, buffer, 256, kCFStringEncodingUTF8)) {
                IOObjectRelease(platformExpert);
                CFRelease(serialNumberAsCFString);
                return QString(buffer);
            }
            CFRelease(serialNumberAsCFString);
        }
        IOObjectRelease(platformExpert);
    }

    // 备用方案
    char hostname[256];
    if (gethostname(hostname, sizeof(hostname)) == 0) {
        return QString(hostname);
    }

#else
    // Linux主板序列号
    QFile file("/sys/class/dmi/id/board_serial");
    if (file.open(QIODevice::ReadOnly)) {
        QString serial = QString::fromUtf8(file.readAll()).trimmed();
        file.close();
        if (!serial.isEmpty() && serial != "None" && serial != "0") {
            return serial;
        }
    }

    // 备用方案：使用machine-id
    QFile machineIdFile("/etc/machine-id");
    if (machineIdFile.open(QIODevice::ReadOnly)) {
        QString machineId = QString::fromUtf8(machineIdFile.readAll()).trimmed();
        machineIdFile.close();
        if (!machineId.isEmpty()) {
            return machineId;
        }
    }
#endif

    return QString();
}

QString SecureTokenManager::getCpuId()
{
#ifdef _WIN32
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 1);

    QString cpuId = QString("%1-%2-%3-%4")
                   .arg(cpuInfo[0], 8, 16, QLatin1Char('0'))
                   .arg(cpuInfo[1], 8, 16, QLatin1Char('0'))
                   .arg(cpuInfo[2], 8, 16, QLatin1Char('0'))
                   .arg(cpuInfo[3], 8, 16, QLatin1Char('0'));

    return cpuId;

#elif __APPLE__
    // macOS CPU信息
    size_t len = 0;
    sysctlbyname("machdep.cpu.brand_string", nullptr, &len, nullptr, 0);

    if (len > 0) {
        QByteArray buffer(len, 0);
        if (sysctlbyname("machdep.cpu.brand_string", buffer.data(), &len, nullptr, 0) == 0) {
            QString cpuBrand = QString::fromUtf8(buffer).trimmed();
            return QCryptographicHash::hash(cpuBrand.toUtf8(), QCryptographicHash::Md5).toHex().left(16);
        }
    }

#else
    // Linux CPU信息
    QFile file("/proc/cpuinfo");
    if (file.open(QIODevice::ReadOnly)) {
        QTextStream in(&file);
        QString line;
        QString processorId;

        while (in.readLineInto(&line)) {
            if (line.startsWith("processor")) {
                QStringList parts = line.split(":");
                if (parts.size() >= 2) {
                    processorId = parts[1].trimmed();
                    break;
                }
            }
        }
        file.close();

        if (!processorId.isEmpty()) {
            return processorId;
        }
    }
#endif

    return QString();
}

QString SecureTokenManager::getMacAddress()
{
    // 获取第一个非回环网络接口的MAC地址
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();

        for (int i = 0; i < interfaces.size(); ++i) {
        const QNetworkInterface& netInterface = interfaces[i];
        // 跳过回环接口和未启用的接口
        if (netInterface.flags() & QNetworkInterface::IsLoopBack ||
            !(netInterface.flags() & QNetworkInterface::IsUp) ||
            !(netInterface.flags() & QNetworkInterface::IsRunning)) {
            continue;
        }

        QString mac = netInterface.hardwareAddress();
        if (!mac.isEmpty() && mac != "00:00:00:00:00:00") {
            return mac.remove(":");
        }
    }

    return QString();
}

QString SecureTokenManager::getVolumeSerial()
{
#ifdef _WIN32
    // 获取系统盘序列号
    DWORD serialNumber;
    if (GetVolumeInformationA("C:\\", nullptr, 0, &serialNumber, nullptr, nullptr, nullptr, 0)) {
        return QString::number(serialNumber);
    }

#else
    // Unix-like系统 - 使用更简单的方法
    struct stat fs;
    if (stat("/", &fs) == 0) {
        // 使用设备ID作为序列号
        return QString::number(fs.st_dev);
    }
#endif

    return QString();
}

QByteArray SecureTokenManager::deriveKeyFromHardware(const QString& salt)
{
    QString actualSalt = salt.isEmpty() ? getSecureSalt() : salt;
    QString hardwareId = m_cachedHardwareId.isEmpty() ? collectHardwareFingerprint() : m_cachedHardwareId;

    // 使用PBKDF2进行密钥派生（Qt6支持）
    QString combined = hardwareId + actualSalt;
    QByteArray key = QCryptographicHash::hash(combined.toUtf8(), QCryptographicHash::Sha256);

    // 扩展到32字节（256位）
    while (key.length() < 32) {
        key += QCryptographicHash::hash(key + QByteArray::number(key.length()), QCryptographicHash::Sha256);
    }

    return key.left(32);
}

QString SecureTokenManager::generateSalt()
{
    QByteArray salt(SALT_LENGTH, 0);
    QRandomGenerator* rng = QRandomGenerator::global();

    for (int i = 0; i < SALT_LENGTH; ++i) {
        salt[i] = static_cast<char>(rng->bounded(256));
    }

    return encodeBase64Safe(salt);
}

QString SecureTokenManager::getSecureSalt()
{
    // 从配置中获取固定的salt，如果没有则生成新的
    QString salt = ConfigManager::getNestedValue("security", "encryptionSalt", "").toString();
    if (salt.isEmpty()) {
        salt = generateSalt();
        ConfigManager::setNestedValue("security", "encryptionSalt", salt);
        ConfigManager::sync();
    }

    return salt;
}

QByteArray SecureTokenManager::encryptAES256GCM(const QByteArray& data, const QByteArray& key, const QByteArray& nonce)
{
    // 注意：这是一个简化版本的AES-GCM实现
    // 在生产环境中，建议使用专业的加密库如OpenSSL

    // 由于Qt不直接支持AES-GCM，这里使用AES-CBC作为替代
    // 同时添加HMAC用于完整性验证

    QByteArray keyHash = QCryptographicHash::hash(key, QCryptographicHash::Sha256);
    QByteArray iv = QCryptographicHash::hash(nonce + key, QCryptographicHash::Md5);

    // 简化的XOR加密（仅作为示例，实际应使用专业的AES实现）
    QByteArray encrypted = data;
    for (int i = 0; i < encrypted.size(); ++i) {
        encrypted[i] ^= keyHash[i % keyHash.size()] ^ iv[i % iv.size()];
    }

    // 添加HMAC
    QByteArray hmac = QCryptographicHash::hash(encrypted + key, QCryptographicHash::Sha256);
    encrypted += hmac.left(16);  // 16字节的HMAC标签

    return encrypted;
}

QByteArray SecureTokenManager::decryptAES256GCM(const QByteArray& encryptedData, const QByteArray& key, const QByteArray& nonce)
{
    if (encryptedData.size() <= 16) {
        return QByteArray();
    }

    // 分离数据和HMAC
    QByteArray data = encryptedData.left(encryptedData.size() - 16);
    QByteArray receivedHmac = encryptedData.right(16);

    // 验证HMAC
    QByteArray expectedHmac = QCryptographicHash::hash(data + key, QCryptographicHash::Sha256).left(16);
    if (receivedHmac != expectedHmac) {
        return QByteArray();
    }

    // 解密数据
    QByteArray keyHash = QCryptographicHash::hash(key, QCryptographicHash::Sha256);
    QByteArray iv = QCryptographicHash::hash(nonce + key, QCryptographicHash::Md5);

    QByteArray decrypted = data;
    for (int i = 0; i < decrypted.size(); ++i) {
        decrypted[i] ^= keyHash[i % keyHash.size()] ^ iv[i % iv.size()];
    }

    return decrypted;
}

QByteArray SecureTokenManager::generateIV()
{
    QByteArray iv(NONCE_LENGTH, 0);
    QRandomGenerator* rng = QRandomGenerator::global();

    for (int i = 0; i < NONCE_LENGTH; ++i) {
        iv[i] = static_cast<char>(rng->bounded(256));
    }

    return iv;
}

QString SecureTokenManager::calculateTokenHash(const QString& token, const QString& salt)
{
    QString combined = token + salt + TOKEN_VERSION + m_cachedHardwareId;
    return QCryptographicHash::hash(combined.toUtf8(), QCryptographicHash::Sha256).toHex();
}

QByteArray SecureTokenManager::encodeBase64Safe(const QByteArray& data)
{
    return data.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}

QByteArray SecureTokenManager::decodeBase64Safe(const QString& data)
{
    return QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}

void SecureTokenManager::recordFailedAttempt(const QString& email)
{
    if (email.isEmpty()) {
        return;
    }

    QString key = FAILED_ATTEMPT_KEY_PREFIX + email;
    int currentAttempts = getFailedAttempts(email);
    currentAttempts++;

    ConfigManager::setNestedValue("security", key, currentAttempts);
    ConfigManager::sync();

}

void SecureTokenManager::clearFailedAttempts(const QString& email)
{
    if (email.isEmpty()) {
        return;
    }

    QString key = FAILED_ATTEMPT_KEY_PREFIX + email;
    ConfigManager::setNestedValue("security", key, 0);
    ConfigManager::sync();

}

int SecureTokenManager::getFailedAttempts(const QString& email)
{
    if (email.isEmpty()) {
        return 0;
    }

    QString key = FAILED_ATTEMPT_KEY_PREFIX + email;
    return ConfigManager::getNestedValue("security", key, 0).toInt();
}

// SecureTokenData 结构体方法实现
QJsonObject SecureTokenData::toJson() const
{
    QJsonObject json;
    json["version"] = version;
    json["encryptedData"] = encryptedData;
    json["nonce"] = nonce;
    json["salt"] = salt;
    json["hash"] = hash;
    json["timestamp"] = timestamp;
    json["expiresAt"] = expiresAt;
    json["failedAttempts"] = failedAttempts;
    return json;
}

SecureTokenData SecureTokenData::fromJson(const QJsonObject& json)
{
    SecureTokenData data;
    data.version = json["version"].toString();
    data.encryptedData = json["encryptedData"].toString();
    data.nonce = json["nonce"].toString();
    data.salt = json["salt"].toString();
    data.hash = json["hash"].toString();
    data.timestamp = json["timestamp"].toVariant().toLongLong();
    data.expiresAt = json["expiresAt"].toVariant().toLongLong();
    data.failedAttempts = json["failedAttempts"].toInt();
    return data;
}

bool SecureTokenData::isValid() const
{
    return !version.isEmpty() &&
           !encryptedData.isEmpty() &&
           !nonce.isEmpty() &&
           !salt.isEmpty() &&
           !hash.isEmpty() &&
           timestamp > 0 &&
           expiresAt > timestamp;
}

QString SecureTokenManager::getHardwareFingerprint() const
{
    return m_cachedHardwareId;
}